# -----------------------------------------------------------------------------------------------
# ===============================================================================================
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# ***********************************************************************************************
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# ...............................................................................................
# ???????????????????????????????????????????????????????????????????????????????????????????????
# ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,


# ## USEFULL FUNCTION

define existDir
$(shell if [ -d $(1) ] ; then echo true ; else echo false ; fi)
endef
define formLib
$(shell if [ ""x == "$(1)"x ] ; then echo "" ; else echo $(addprefix $(FOLDER_LIB)/,$(1)) ; fi)
endef
define formDll
$(shell if [ ""x == "$(1)"x ] ; then echo "" ; else echo $(addprefix $(FOLDER_DLL)/$(basename $(notdir $(1)))/,$(1)) ; fi)
endef
define chgsuffix
$(addsuffix $(1),$(basename $(2)))
endef
define chgprefix
$(addprefix $(1),$(notdir $(2)))
endef
define chgfix
$(call chgprefix,$(1),$(call chgsuffix,$(3),$(2)))
endef
define addffix
$(addpreffix $(1),$(addsuffix $(3),$(2)))
endef
define puredir
$(patsubst %/,%,$(dir $(1)))
endef


# -----------------------------------------------------------------------------------------------
# ## FRAME SET

PLATFORM=windows# use to choose flag table(avaliable: windows)
# THIRD_PART=
# FOLDER_3rdPART=
.PHONY : all main initDir allinall copydll $(MAKECMDGOALS)
ifeq ($(strip $(MAKECMDGOALS)),)
all:allinall
else
$(MAKECMDGOALS):main;@echo [done]
endif
# -----------------------------------------------------------------------------------------------


# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# ## SET FLAGS

# [platform specific]
# suffix_src=
# suffix_obj=
# suffix_lib=
# suffix_dll=

# compiler=
# libmanager=
# linker=

# flag_src2obj=
# flag_obj2lib=
# flag_obj2dll1=
# flag_obj2dll2=

# flag_outobj=
# flag_outlib=
# flag_outdll=

ifeq ($(PLATFORM),windows)
suffix_src=.cpp
suffix_obj=.obj
suffix_lib=.lib
suffix_dll=.dll
suffix_exp=.exp

flag_common=/nologo

compiler=cl
flag_src2libobj=$(flag_common) /c
flag_src2dllobj=$(flag_common) /c /EHsc# that's the short part
flag_outobj=/Fo
flag_outexe=/Fe

libmanager=LIB
flag_obj2lib=$(flag_common) 
flag_obj2dll1=$(flag_common) /DEF
flag_outlib=/OUT:

linker=LINK
flag_obj2dll2=$(flag_common) /DLL
flag_outdll=/OUT:
endif
# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


# ===============================================================================================
# ## SELECT FOLDER

FOLDER_SRC=exts/$(MAKECMDGOALS)
FOLDER_INCLUDE=exts/$(MAKECMDGOALS)
FOLDER_INLINE=exts/$(MAKECMDGOALS)
FOLDER_RST=build/exts
# FOLDER_LIB=
FOLDER_DLL=$(FOLDER_RST)/dll
FOLDER_OBJ=$(FOLDER_RST)/obj
# FOLDER_LIBOBJ=
FOLDER_DLLOBJ=$(FOLDER_OBJ)
ifdef THIRD_PART
ifdef FOLDER_3rdPART
FOLDER_3rdPART_RST=$(FOLDER_RST)/$(FOLDER_3rdPART)
else
FOLDER_3rdPART_RST=$(FOLDER_RST)/rely
endif
endif
# ===============================================================================================


# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# ## SELECT CODE

# OUTPUT_LIB1=Environment.lib
# OUTPUT_LIBSRC1=\
# lencucu_Environment.cpp
#... LIBs

OUTPUT_DLL:=$(MAKECMDGOALS).dll
OUTPUT_DLLSRC:=$(MAKECMDGOALS).cpp
TARGET_CLUSTER_DLL:=$(call formDll,$(OUTPUT_DLL))
TARGET_CLUSTER:=$(TARGET_CLUSTER_DLL)
TARGET_CLUSTER_DLLSRC:=$(sort $(OUTPUT_DLLSRC))
TARGET_CLUSTER_SRC:=$(TARGET_CLUSTER_DLLSRC)# just for initDir to detect
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


# ***********************************************************************************************
# ## CODE RELY
# for the precision of compiling

define fresh
	@cat $@>$(call chgsuffix,.freshcpp,$@)
	@cat $(call chgsuffix,.freshcpp,$@)>$@
	@rm $(call chgsuffix,.freshcpp,$@)
endef

# $(FOLDER_SRC)/lencucu_Environment.cpp:$(addprefix $(FOLDER_INCLUDE)/,lencucu_Environment.hpp);$(fresh)
# $(FOLDER_INCLUDE)/lencucu_Environment.hpp:$(addprefix $(FOLDER_INLINE)/,lencucu_Environment.inl);$(fresh)
# ***********************************************************************************************


# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# ## CONTENT

ifneq ($(strip $(TARGET_CLUSTER)),)
main:initDir $(TARGET_CLUSTER)
else
main:test
endif


# form folder
initDir:
	@mkdir -p $(FOLDER_RST)/../program/obj
	@# [ ROOT FOLDER PART ]
ifdef TARGET_CLUSTER
ifdef TARGET_CLUSTER_SRC
ifeq ($(call existDir,$(FOLDER_RST)),false)
	@mkdir -p $(FOLDER_RST)
endif
ifeq ($(call existDir,$(FOLDER_OBJ)),false)
	@mkdir -p $(FOLDER_OBJ)
endif
	@# hold
	@# hold
	@# [ LIB FOLDER PART ]
ifdef TARGET_CLUSTER_LIB
ifdef TARGET_CLUSTER_LIBSRC
ifeq ($(call existDir,$(FOLDER_LIBOBJ)),false)
	@mkdir -p $(FOLDER_LIBOBJ)
endif
ifeq ($(call existDir,$(FOLDER_LIB)),false)
	@mkdir -p $(FOLDER_LIB)
endif
endif
endif
	@# hold
	@# hold
	@# [ DLL FOLDER PART ]
ifdef TARGET_CLUSTER_DLL
ifdef TARGET_CLUSTER_DLLSRC
ifeq ($(call existDir,$(FOLDER_DLLOBJ)),false)
	@mkdir -p $(FOLDER_DLLOBJ)
endif
ifeq ($(call existDir,$(FOLDER_DLL)),false)
	@mkdir -p $(FOLDER_DLL)
endif
endif
endif
	@# hold
	@# hold
endif
endif


allinall:
	@$(compiler) $(flag_common) $(flag_outobj)$(FOLDER_RST)/../program/obj/ $(flag_outexe)$(FOLDER_RST)/../program/ main.cpp
	@echo [done]
copydll:
	@cp $(FOLDER_DLL)/*/*$(suffix_dll) $(FOLDER_RST)/../program



DLLOBJS=$(call chgfix,$(FOLDER_DLLOBJ)/,$(TARGET_CLUSTER_DLLSRC),$(suffix_obj))
$(DLLOBJS):$(FOLDER_DLLOBJ)/%$(suffix_obj):$(FOLDER_SRC)/%$(suffix_src)
	@$(compiler) $(flag_src2dllobj) $(flag_outobj)$@ $<


# build/dll/xxx/xxx.dll:build/obj/dll/xxx.obj...
$(call formDll,$(OUTPUT_DLL)):$(call chgfix,$(FOLDER_DLLOBJ)/,$(OUTPUT_DLLSRC),$(suffix_obj))
	@echo [building dll] $(notdir $@)
	@# $@ just work during perform
ifeq ($(call existDir,$(call chgfix,$(FOLDER_DLL)/,$(OUTPUT_DLL),)),false)
	@mkdir -p $(call puredir,$@)
endif
	@$(libmanager) $(flag_obj2dll1) $(flag_outlib)$(call chgsuffix,$(suffix_lib),$@) $^
	@$(linker) $(flag_obj2dll2) $(flag_outdll)$@ $(call chgsuffix,$(suffix_exp),$@) $^
	@cp $@ $(FOLDER_RST)/../program
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


# ???????????????????????????????????????????????????????????????????????????????????????????????
# ## TEST PART

# ???????????????????????????????????????????????????????????????????????????????????????????????
